package com.jwsoft.manager.core.dao.service.impl;

import cn.hutool.core.convert.Convert;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.module.base.common.util.CommonSecureUtil;
import com.jwsoft.manager.common.constant.EduCache;
import com.jwsoft.manager.common.enums.EduStatusTypeEnum;
import com.jwsoft.manager.common.vo.eduDataTaskDetail.DataTaskDetailOptionVO;
import com.jwsoft.manager.common.vo.eduStudentEnroll.StudentFormVO;
import com.jwsoft.manager.common.vo.eduStudentEnrollKindergarten.KindergartenCompareVO;
import com.jwsoft.manager.common.vo.eduStudentEnrollVerification.EduStudentEnrollVerificationVO;
import com.jwsoft.manager.core.dao.mapper.EduhStudentEnrollKindergartenMapper;
import com.jwsoft.manager.core.dao.mapper.EdutStudentEnrollKindergartenMapper;
import com.jwsoft.manager.core.dao.model.*;
import com.jwsoft.manager.core.dao.mapper.EduStudentEnrollKindergartenMapper;
import com.jwsoft.manager.core.dao.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 表单提交明细表服务实现类
 *
 * @author chenzh
 * @since 2023-02-10
 */
@Service
@Slf4j
public class EduStudentEnrollKindergartenServiceImpl extends ServiceImpl<EduStudentEnrollKindergartenMapper, EduStudentEnrollKindergarten> implements EduStudentEnrollKindergartenService, TableService {
    @Autowired
    private EduDataTaskDetailService detailService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private EduhStudentEnrollKindergartenMapper hKindergartenMapper;

    @Autowired
    private EdutStudentEnrollKindergartenMapper tKindergartenMapper;
    @Autowired
    private EduStudentEnrollVerificationService eduStudentEnrollVerificationService;
    //每次处理的数量为1w条数据
    private static final Integer PAGE_SIZE = 10000;
    /**
     * 我的报名数据缓存1小时
     * */
    @Override
    @Cached(name = EduCache.EDU_MY_ENROLL, key = "#idcard", cacheType = CacheType.BOTH, expire = 3600, localExpire = 20)
    public List<StudentFormVO> getMyNurseryInfo(String idcard) {
        List<StudentFormVO> retList=this.baseMapper.getMyNurseryInfo(idcard);
        if(!CollectionUtils.isEmpty(retList)){
            List<String> enrollIdList=retList.stream().map(StudentFormVO::getStudentEnrollId).distinct().collect(Collectors.toList());
            QueryWrapper<EduStudentEnrollVerification> queryWrapper=new QueryWrapper<>();
            queryWrapper.lambda().in(EduStudentEnrollVerification::getStudentEnrollId,enrollIdList);
            List<EduStudentEnrollVerification> list=eduStudentEnrollVerificationService.list(queryWrapper);
            if (!CollectionUtils.isEmpty(list)){
                Map<String,List<EduStudentEnrollVerification>> groupby=list.stream().collect(Collectors.groupingBy(EduStudentEnrollVerification::getStudentEnrollId));
                for(StudentFormVO result:retList){
                    List<EduStudentEnrollVerification> verificationList=groupby.get(result.getStudentEnrollId());
                    if(!CollectionUtils.isEmpty(verificationList)){
                        result.setVerificationVOList(Convert.toList(EduStudentEnrollVerificationVO.class,verificationList));
                    }else{
                        result.setVerificationVOList(new ArrayList<>());
                    }

                }
            }

        }

        return retList;
    }

    @Override
    public Long queryMaxApplyId(String formId) {
        return this.baseMapper.queryMaxApplyId(formId);
    }

    @Override
    public List<EduStudentEnrollKindergarten> queryDelByIdcard(String idcard, String schoolId,String areaCode) {
        return this.baseMapper.queryDelByIdcard(idcard,schoolId,areaCode);
    }

    @Override
    public List<KindergartenCompareVO> getNurseryHouseCompareData(KindergartenCompareVO vo) {
        return baseMapper.getNurseryHouseCompareData(vo);
    }

    @Override
    public List<KindergartenCompareVO> getNurseryHouseHoldCompareData(KindergartenCompareVO vo) {
        return baseMapper.getNurseryHouseHoldCompareData(vo);
    }


    @Override
    public Integer dataMigration(DataTaskDetailOptionVO optionVO) {
        EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
        log.info("调用了EduStudentEnrollKindergartenServiceImpl服务的dataMigration()来进行处理迁移数据");
        Integer count = this.baseMapper.selectCountByYear(optionVO.getYear());
        log.info("edu_student_enroll_kindergarten迁移" + count + "条数据");
        int totalPages = (count % PAGE_SIZE == 0) ? (count / PAGE_SIZE) : (count / PAGE_SIZE + 1);
        for (int i = 0; i < totalPages; i++) {
            List<EduStudentEnrollKindergarten> studentEnrollKindergartens =
                    this.baseMapper.selectByYear(optionVO.getYear(), PAGE_SIZE);
            if (studentEnrollKindergartens.size() > 0) {
                List<EduhStudentEnrollKindergarten> hKindergartens = studentEnrollKindergartens.stream().map(item -> {
                    EduhStudentEnrollKindergarten kindergarten = new EduhStudentEnrollKindergarten();
                    BeanUtils.copyProperties(item, kindergarten);
                    kindergarten.setTaskDetailId(taskDetail.getTaskDetailId());
                    kindergarten.setEncryptFlag(BoolEnum.FALSE.getType());
                    kindergarten.setEncryptStatus(EduStatusTypeEnum.dcl.getType());
                    kindergarten.setCleanFlag(BoolEnum.FALSE.getType());
                    return kindergarten;
                }).collect(Collectors.toList());
                try {
                    this.performDataMigration(hKindergartens, studentEnrollKindergartens.size(), optionVO);
                } catch (Exception e) {
                    log.error("edu_student_enroll_kindergarten迁移数据发生异常");
                    throw new RuntimeException("EduStudentEnrollKindergartenServiceImpl:" + e);
                }
            }
        }
        return count;
    }

    private void performDataMigration(List<EduhStudentEnrollKindergarten> hKindergartens, Integer count, DataTaskDetailOptionVO optionVO) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    //1.数据迁移到历史表
                    int saveHCount = hKindergartenMapper.saveBatch(hKindergartens);
                    if (saveHCount != count) {
                        throw new RuntimeException("数据迁移到历史表失败");
                    }
                    //2.数据销毁
                    EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
                    if (ObjectUtils.isEmpty(taskDetail)) {
                        throw new AppException("任务数据不存在，请检查数据是否有误");
                    }
                    Integer deleteCount = baseMapper.deleteByTaskHistory(taskDetail.getTaskDetailId());
                    if (!count.equals(deleteCount)) {
                        throw new RuntimeException("数据删除失败");
                    }
                    log.info("edu_student_enroll_kindergarten数据销毁成功！销毁数量：" + count);
                } catch (Exception e) {
                    status.setRollbackOnly();
                    throw e;
                }
            }
        });
        }

    @Override
    public void dataEncryption(DataTaskDetailOptionVO optionVO) {
        EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
        log.info("调用了EduStudentEnrollKindergartenServiceImpl服务的dataEncryption()来进行处理数据加密");
        Integer count = 0;
        if (taskDetail.getEncryptCount() == 0) {
            count = this.baseMapper.selectEncryptionCountByYear(optionVO.getYear(), optionVO.getTaskDetailId());
            taskDetail.setEncryptCount(count);
        }
        Boolean errorFlag = false;
        Integer errorCount = 0;
        // 计算总页数
        int totalPages = (count % PAGE_SIZE == 0) ? (count / PAGE_SIZE) : (count / PAGE_SIZE + 1);
        // 计算循环次数 = 总页数
        for (int i = 0; i < totalPages; i++) {
            List<EduhStudentEnrollKindergarten> hKindergartens =
                    this.baseMapper.selectEncryptionByYear
                            (optionVO.getYear(), optionVO.getTaskDetailId(), PAGE_SIZE);
            for (EduhStudentEnrollKindergarten hKindergarten : hKindergartens) {
                try {
                    this.encrypt(hKindergarten);
                    hKindergarten.setEncryptTime(new Date());
                    hKindergarten.setEncryptStatus(EduStatusTypeEnum.success.getType());
                    hKindergarten.setEncryptRemarks("加密成功");
                    hKindergarten.setEncryptFlag(BoolEnum.TRUE.getType());
                    hKindergartenMapper.updateById(hKindergarten);
                }catch (Exception e){
                    this.decrypt(hKindergarten);
                    hKindergarten.setEncryptTime(new Date());
                    hKindergarten.setEncryptStatus(EduStatusTypeEnum.error.getType());
                    hKindergarten.setEncryptFlag(BoolEnum.FALSE.getType());
                    hKindergarten.setEncryptRemarks("加密失败"+e.getMessage());
                    hKindergartenMapper.updateById(hKindergarten);
                    errorFlag = true;
                    errorCount++;
                    throw new AppException(e);
                }
            }
       }
        if (!errorFlag) {
            //无异常，返回任务状态
            taskDetail.setEncryptStatus(EduStatusTypeEnum.success.getType());
            taskDetail.setEncryptRemarks("加密成功");
            taskDetail.setEncryptTime(new Date());
        } else {
            taskDetail.setEncryptStatus(EduStatusTypeEnum.error.getType());
            taskDetail.setEncryptTime(new Date());
            taskDetail.setEncryptRemarks(taskDetail.getHandleTable()
                    +"加密失败,加密出错的数据：" + errorCount);
        }
        detailService.updateById(taskDetail);
    }

    private void decrypt(EduhStudentEnrollKindergarten hKindergarten) {
        if (StringUtils.isNotBlank(hKindergarten.getChildFullName())){
            hKindergarten.setChildFullName(CommonSecureUtil.sm4Decrypt(hKindergarten.getChildFullName()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getChildIdcard())){
            hKindergarten.setChildIdcard(CommonSecureUtil.sm4Decrypt(hKindergarten.getChildIdcard()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getChildShortName())){
            hKindergarten.setChildShortName(CommonSecureUtil.sm4Decrypt(hKindergarten.getChildShortName()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getAddress())){
            hKindergarten.setAddress(CommonSecureUtil.sm4Decrypt(hKindergarten.getAddress()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getFatherName())){
            hKindergarten.setFatherName(CommonSecureUtil.sm4Decrypt(hKindergarten.getFatherName()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getFatherIdcard())){
            hKindergarten.setFatherName(CommonSecureUtil.sm4Decrypt(hKindergarten.getFatherIdcard()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getFatherPhone())){
            hKindergarten.setFatherPhone(CommonSecureUtil.sm4Decrypt(hKindergarten.getFatherPhone()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getMotherName())){
            hKindergarten.setMotherName(CommonSecureUtil.sm4Decrypt(hKindergarten.getMotherName()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getMotherIdcard())){
            hKindergarten.setMotherIdcard(CommonSecureUtil.sm4Decrypt(hKindergarten.getMotherIdcard()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getMotherPhone())){
            hKindergarten.setMotherPhone(CommonSecureUtil.sm4Decrypt(hKindergarten.getMotherPhone()));
        }
    }

    private void encrypt(EduhStudentEnrollKindergarten hKindergarten) {
        if (StringUtils.isNotBlank(hKindergarten.getChildFullName())){
            hKindergarten.setChildFullName(CommonSecureUtil.sm4Encrypt(hKindergarten.getChildFullName()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getChildIdcard())){
            hKindergarten.setChildIdcard(CommonSecureUtil.sm4Encrypt(hKindergarten.getChildIdcard()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getChildShortName())){
            hKindergarten.setChildShortName(CommonSecureUtil.sm4Encrypt(hKindergarten.getChildShortName()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getAddress())){
            hKindergarten.setAddress(CommonSecureUtil.sm4Encrypt(hKindergarten.getAddress()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getFatherName())){
            hKindergarten.setFatherName(CommonSecureUtil.sm4Encrypt(hKindergarten.getFatherName()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getFatherIdcard())){
            hKindergarten.setFatherName(CommonSecureUtil.sm4Encrypt(hKindergarten.getFatherIdcard()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getFatherPhone())){
            hKindergarten.setFatherPhone(CommonSecureUtil.sm4Encrypt(hKindergarten.getFatherPhone()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getMotherName())){
            hKindergarten.setMotherName(CommonSecureUtil.sm4Encrypt(hKindergarten.getMotherName()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getMotherIdcard())){
            hKindergarten.setMotherIdcard(CommonSecureUtil.sm4Encrypt(hKindergarten.getMotherIdcard()));
        }
        if (StringUtils.isNotBlank(hKindergarten.getMotherPhone())){
            hKindergarten.setMotherPhone(CommonSecureUtil.sm4Encrypt(hKindergarten.getMotherPhone()));
        }

    }

    @Override
    public Integer dataDestruction(DataTaskDetailOptionVO optionVO) {
        return null;
    }

    @Override
    public void tempDataDestruction() {

    }

    @Override
    public void dataDecrypt(DataTaskDetailOptionVO optionVO) {
        Integer count = Math.toIntExact(hKindergartenMapper.selectCount(new QueryWrapper<EduhStudentEnrollKindergarten>().lambda().eq(EduhStudentEnrollKindergarten::getTaskDetailId, optionVO.getTaskDetailId())));
        // 计算总页数
        int totalPages = (count % PAGE_SIZE == 0) ? (count / PAGE_SIZE) : (count / PAGE_SIZE + 1);
        int currentPage = 0;
        // 计算循环次数 = 总页数
        for (int i = 0; i < totalPages; i++) {
            List<EduhStudentEnrollKindergarten> hKindergartens =
                    hKindergartenMapper.selectByTaskDetailId(optionVO.getTaskDetailId(),currentPage,PAGE_SIZE);
            List<EdutStudentEnrollKindergarten> tKindergartens = hKindergartens.stream().map(item -> {
                if (BoolEnum.TRUE.getType().equalsIgnoreCase(item.getEncryptFlag())) {
                    //需要进行解密
                    this.decrypt(item);
                }
                EdutStudentEnrollKindergarten tKindergarten = new EdutStudentEnrollKindergarten();
                BeanUtils.copyProperties(item, tKindergarten);
                return tKindergarten;
            }).collect(Collectors.toList());
            tKindergartenMapper.saveBatch(tKindergartens);
            currentPage ++;
        }
    }
}
